#ifndef CNC_UI_WIN32_DESKTOP_IMPLEMENTATION_H
#define CNC_UI_WIN32_DESKTOP_IMPLEMENTATION_H

#include "window.h"
// provided interfaces
#include "taskctl.h"
#include "uiservs.h"
#include "vkeyboard.h"
// required interfaces
#include "millpdata.h" // TODO: rename to cncpdata.h
#include "globaldata.h"
#include "progmgr.h"
#include "enventities.h"
// basic component model
#include <bcm/bcm.h>
// header files

namespace cnc {

	namespace ui {

		/**
		@brief Win32 Desktop GUI Implementation.
		
		This class implements a classic Win32 desktop GUI.
		*/

		class Win32DesktopImpl : public bcm::Identifier<cnc::base::TaskControl>,
			public bcm::Identifier<Services>,
			public bcm::Identifier<VirtualKeyboard>
		{
		protected:
			unsigned count_;
			Window window_;
		protected:
			Win32DesktopImpl() : bcm::Identifier<TaskControl>("taskctl", "Task Control"),
				bcm::Identifier<Services>("uiservs", "User Interface Services"),
				bcm::Identifier<VirtualKeyboard>("vkbd", "Virtual Keyboard"),
				count_(0)
			{
			}
			cnc::base::TaskControl *getTaskControl()
			{
				return static_cast<cnc::base::TaskControl *>(this);
			}
			Services *getServices()
			{
				return static_cast<Services *>(this);
			}
			VirtualKeyboard *getVirtualKeyboard()
			{
				return static_cast<VirtualKeyboard *>(this);
			}
			void setPersistentData(cnc::base::MillPersistentData *pd)
			{
				window_.setPersistentData(pd);
			}
			void setGlobalData(cnc::base::GlobalData *gd)
			{
				window_.setGlobalData(gd);
			}
			void setProgramManager(cnc::compiler::ProgramManager *pm)
			{
				window_.setProgramManager(pm);
			}
			void setEnvironmentEntities(cnc::rtl::EnvironmentEntities *env)
			{
				window_.setEnvironmentEntities(env);
			}
		protected: // Task Control
			bool start()
			{
				if (window_.canStart() == false)
					return false;
				count_++;
				window_.createWindow();
				return true;
			}
			bool execute()
			{
				if (canExecute() == false)
					return false;
				MSG message;
				if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) {
					/* Translate virtual-key messages into character messages */
					TranslateMessage(&message);
					/* Send message to WindowProcedure */
					DispatchMessage(&message);
					if (message.message == WM_QUIT)
						return false;
				}
				return true;
			}
			bool stop()
			{
				if (count_ == 0)
					return false;
				count_--;
				window_.destroyWindow();
				return true;
			}
			bool canExecute()
			{
				return count_ > 0;
			}
		protected: // UI Manager
			
			bool selectForm(const char *formID)
			{
				return window_.selectForm(formID);
			}
			bool setInfo(const char *infoID, const char *utf8text)
			{
				return true;
			}
			void setCommand(const cnc::comm::KbdCommand kbdCmd)
			{
			}
		protected: // Virtual Keyboard
			bool getCommand(cnc::comm::KbdCommand *kbdCmd)
			{
				return window_.getCommand(kbdCmd);
			}
			bool setState(int category, int option)
			{
				return true;
			}
			int getState(int category, int option = -1)
			{
				return -1;
			}
		};

	} // namespace ui

} // namespace cnc

#endif

